import React, { useCallback, useState, useEffect, useRef, useMemo } from 'react';
import { Input, Button } from 'antd-mobile';
import { Common, PageCommon } from 'UtilsCommon';
import { Icon } from 'Configs';
import Components from 'Components';
import Base from './base';

const validateFile = (file, property, pageAxis) => {
    if (property.acceptType) {
        const reg = new RegExp(property.acceptType, "i");

        const names = file.name.split('.');
        const ft = '.' + names[names.length - 1];

        if (!reg.test(ft)) {
            pageAxis.showMessage('请上传' + property.acceptType + '文件！');
            return false;
        }
    }

    property.isImage2 = /image/.test(file.type);

    if (property.isImage2) property.fileSize = 1024 * 1024 * 10;

    if (property.fileSize > 0 && file.size > property.fileSize) {
        if (!property.fileSizeText) property.fileSizeText = Common.getFileSizeText(property.fileSize);
        pageAxis.showMessage('上传文件大小不能大于' + property.fileSizeText + '！');
        return false;
    }

    return true;
};

const invokeUploadFile = (fileInput, file, pageAxis, property, setValue, setLoading, width, height) => {
    const formData = new FormData();
    formData.append('file', file, file.name);

    let pathQuery = "";

    if (property.isImage) pathQuery += `?width=${width}&height=${height}`;

    if (property.getParameter) {
        const parameters = pageAxis.getFunction(property.getParameter);
        if (parameters) pathQuery += parameters();
    }

    if (!property.multiple) setLoading(true);

    if (!property.serviceInterface) {
        property.serviceInterface = {
            serviceName: property.serviceName || 'FileService',
            actionName: property.isImage ? "uploadImage" : 'uploadFile'
        };
    }
    const { serviceName, actionName } = property.serviceInterface;

    return pageAxis.dispatchAction(serviceName, actionName, { pathQuery, formData, isLoading: !property.multiple }).then(res => {
        if (pageAxis.isSuccessProps(res)) {
            if (property.uploadCallback) {
                const uploadCallback = pageAxis.getFunction(property.uploadCallback);
                if (uploadCallback) uploadCallback({ res, property });
            }
            else setValue(res.FileUrl);
        }

        if (!property.multiple) {
            setLoading(false);
            fileInput.value = '';
        }
        return Promise.resolve(true);
    });
};

const uploadFile = (e, pageAxis, property, setValue, setLoading) => {
    const fileInput = e.target;
    if (fileInput.files.length === 0) return;

    let blSuccess = true;
    for (let i = 0; i < fileInput.files.length; i++) {
        const file = fileInput.files[i];
        if (!validateFile(file, property, pageAxis)) {
            fileInput.value = '';
            blSuccess = false;
            break;
        }
    }
    if (!blSuccess) return;

    if (property.multiple) {
        setLoading(true);
        PageCommon.setLoading(true, true, '文件正在上传中...');
    }

    const fileList = [];

    for (let i = 0; i < fileInput.files.length; i++) {
        const file = fileInput.files[i];
        if (property.isImage2 && !property.multiple) {
            getImage(file, property).then(img => {
                invokeUploadFile(fileInput, img, pageAxis, property, setValue, setLoading);
            });
        }
        else if (property.isImage && !property.multiple) {
            Common.getImageFileWidthHeight(file).then(res => {
                invokeUploadFile(fileInput, file, pageAxis, property, setValue, setLoading, res.width, res.height);
            });
        }
        else fileList.push(invokeUploadFile(fileInput, file, pageAxis, property, setValue, setLoading));
    }

    if (property.multiple) {
        Promise.all(fileList).then(() => {
            fileInput.value = '';
            setLoading(false);
            PageCommon.setLoading(false);
        });
    }
};

const getImage = (file, property) => {
    if (!property.maxSize) property.maxSize = 1024 * 1024;
    if (!property.quality) property.quality = 0.6;
    if (!property.imageType) property.imageType = 'image/jpeg';
    const { width, height, imageType, quality, maxWidth, maxHeight, maxSize } = property;

    if (maxSize && file.size < maxSize) return Promise.resolve(file);

    return Common.compressImage(file, width, height, imageType, quality, maxWidth, maxHeight).then(res => {
        return Promise.resolve(Common.dataURLtoFile(res, file.name));
    });
};

const renderImage = (value) => {
    if (!value) return;
    return <div className={'divImage'}>
        <img src={value} alt='' />
    </div>;
};

export default (props) => {
    const { property, pageId, pageAxis } = Base.getProps(props);

    const [isVisible, setIsVisible] = useState(property.isVisible !== false);
    const obj = useMemo(() => ({}), []);
    const [value, setValue] = useState(Base.getInitValue(property, obj) || '');
    const [disabled, setDisabled] = useState(!!property.disabled);
    const [isReadOnly, setIsReadOnly] = useState(!!property.isReadOnly);
    const [loading, setLoading] = useState(false);

    const onChangeText = useCallback((v) => {
        setValue(v);
    }, [setValue]);

    const inputFile = useRef(null);

    const onChange = useCallback((e) => {
        uploadFile(e, pageAxis, property, setValue, setLoading);
    }, [pageAxis, property, setValue, setLoading]);

    const onClick = useCallback(() => {
        if (disabled || isReadOnly || loading) return;
        inputFile.current.click();
    }, [inputFile, disabled, isReadOnly, loading]);

    useEffect(() => {
        Base.bindDataValue(property, value);
    }, [property, value]);

    property.setIsVisible = (v) => { property.isVisible = v; setIsVisible(v); };
    property.setValue = (v) => setValue(v);
    property.getValue = () => value;
    property.setDisabled = (v) => setDisabled(v);
    property.setIsReadOnly = (v) => setIsReadOnly(v);

    if (!isVisible) return null;

    const isTextVisible = property.isTextVisible !== false;

    const { accept, labelStyle, isImage, isShowImage, isPropertyView, className, style, isAddColon, isRed, label, isNullable } = property;

    const isRed2 = property.isRed2 || (isNullable === false && isRed);

    const label2 = property.isLabel === false ? '' : label;

    return (
        <div className={className} style={Base.setStyle(style)}>
            {label2 && <div style={Base.setStyle(labelStyle)}>
                {isRed2 ? <span style={{ color: 'red', position: 'relative', paddingRight: '0.125rem', top: '0.125rem' }}>*</span> : ''}
                {label2}{isAddColon ? '：' : ''}
            </div>}
            {isImage && isShowImage && renderImage(value)}
            {isTextVisible && <Input placeholder={property.placeHolder}
                onChange={onChangeText}
                maxLength={property.maxLength}
                readOnly={isReadOnly}
                disabled={disabled && !isReadOnly}
                type='text'
                clearable={!isReadOnly && !disabled}
                value={value} />}
            {isTextVisible && <div className='divWhiteSapce'></div>}
            {!isPropertyView && <div className='divButton'>
                <Button disabled={disabled || isReadOnly} loading={loading} onClick={onClick} style={property.buttonStyle}>
                    <Icon type='upload' /> 上传
                </Button>
                {property.tip && <div className='divTip'><span>{property.tip}</span></div>}
            </div>}
            {isPropertyView && property.properties && <div onClick={onClick} style={property.buttonStyle}>
                {!loading && Components.Base.renderProperties(property, pageId)}
                {loading && <span style={property.upSpanStyle}>上传中...</span>}
            </div>}
            <input type='file' accept={accept} multiple={property.multiple} onChange={onChange} ref={inputFile} style={{ display: 'none' }} />
        </div>
    );
};